package hanlen.mq.starter;

import hanlen.mq.starter.annotation.RedisSubscribe;
import hanlen.mq.starter.core.RedissonService;
import java.lang.reflect.Method;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.client.codec.Codec;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author weaponry MrYe
 * @program purchaser-assist-service
 * @created 2020-09-25 15:21
 */
@Slf4j
public class RedisSubscribeBean<T> implements InitializingBean, ApplicationContextAware {

    private ApplicationContext context;
    private final T ref;
    private final List<Method> methods;

    RedisSubscribeBean(T ref, List<Method> methods) {
        this.ref = ref;
        this.methods = methods;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @Override
    public void afterPropertiesSet() {
        methods.forEach(m -> {
            final RedisSubscribe annotation = m.getAnnotation(RedisSubscribe.class);
            final RTopic topic = context.getBean(RedissonService.class).getTopic(annotation.topicName(),
                (Codec) ReflectUtils.newInstance(annotation.codec()));
            topic.addListener(annotation.msgType(), (charSequence, data) -> {
                try {
                    m.invoke(ref, data);
                } catch (Exception e) {
                    log.error("Redis发布订阅 error:", e);
                }
            });
            log.info("Redis发布订阅 注册Topic:{} {} 成功", annotation.topicName(), topic);
        });
    }

    void removeAllListener() {
        methods.forEach(m -> {
            final RedisSubscribe service = m.getAnnotation(RedisSubscribe.class);
            final RTopic topic = context.getBean(RedissonService.class).getTopic(service.topicName(),
                (Codec) ReflectUtils.newInstance(service.codec()));
            topic.removeAllListeners();
            log.info("Redis发布订阅 移除Topic:{} {} 成功", service.topicName(), topic);
        });
    }

}
